package com.yq.interview.study.thread;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @ClassName ContainerNotSafeDemo
 * @Description 集合类不安全的问题
 * ArrayList是线程不安的，编写一个线程不安全的案例并给出解决方案
 * 创建一个arrayList，for循环30次，里面嵌套3个new Thread(()->{}).start();{}里面list.add(UUID.randomUUID().toString().substring(0,8))添加
 * @Author yaoqiang
 * @Date 2020/11/18 13:50
 * @Version 1.0
 */
public class ContainerNotSafeDemo {
    public static void main(String[] args) {

     //   testArrayListNotSafeDemo();

     //   testSetNotSafeDemo();
//map
        testMapNotSafeDemo();

    }

    private static void testMapNotSafeDemo() {
      //  Map<String,String> map=new HashMap<>();
      //  Map<String,String> map=Collections.synchronizedMap(new HashMap<>());
        Map<String,String> map= new ConcurrentHashMap<>();
        for (int i=1;i<=30;i++){
            new Thread(()->{
                map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0,8));
                System.out.println(map);
            },String.valueOf(i)).start();
        }
    }

    /**
     * 1、故障现象：java.util.ConcurrentModifictionException
     * 2、原因
     * 3、解决方式
     * 4、优化
     */
    public static void testSetNotSafeDemo(){
      //  Set<String> set=new HashSet<>();
      //  Set<String> set= Collections.synchronizedSet(new HashSet<>());
        Set<String> set= new CopyOnWriteArraySet();
        set.add("a");
        for (int i=1;i<=30;i++){
            new Thread(()->{
                set.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(set);
            },String.valueOf(i)).start();
        }
        new HashSet<>();//    public HashSet() {map = new HashMap<>(); }
//        public boolean add(E e) {
//            return map.put(e, PRESENT)==null;//    private static final Object PRESENT = new Object(); hash
//        }
    }


    /**
     *1、故障现象： java.util.ConcurrentModificationException
     *
     *2、导致原因
     * 并发争抢修改导致异常，一个线程正在写入，另一个线程过来争抢，导致数据不一致异常，并发修改异常
     *
     * 3、解决方案
     *  3.1 new Vactor();//里面加锁了
     *  3.2 Collections.synchronizedList(new ArrayList<>());//构建一个线程安全，可以把一个线程不安全的变成线程安全的
     *  3.3 JUC下的CopyOnWriteArrayList() 写时复制，是一种读写分离的策略
     复制一个新的容器 Object[] newElements,往新的容器里添加元素，添加完成后将原容器的的引用指向新容器setArray(newElement)

     final transient ReentrantLock lock = new ReentrantLock();

     public boolean add(E e) {
     final ReentrantLock lock = this.lock;
     lock.lock();
     try {
     Object[] elements = getArray();
     int len = elements.length;
     Object[] newElements = Arrays.copyOf(elements, len + 1);
     newElements[len] = e;
     setArray(newElements);
     return true;
     } finally {
     lock.unlock();
     }
     }
     *
     * 4、优化建议
     */
    public static void testArrayListNotSafeDemo(){
        //ArrayList线程
        // List<String> list= new Vector<>();
        //  List<String> list= new ArrayList<>();
        // List<String> list= Collections.synchronizedList(new ArrayList<>());//构建一个线程安全
        List<String> list = new CopyOnWriteArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");

//        List<String> list= Arrays.asList("a","b","c");
//        list.forEach(System.out::println);

        //三个线程操作
        //arrayList的高并发-并发修改异常 java.util.ConcurrentModificationException
        for (int i = 1; i <= 30; i++) {
            new Thread(() -> {
                list.add(UUID.randomUUID().toString().substring(0, 8));
                System.out.println(list);
            }, String.valueOf(i)).start();
        }

    }

}
